package com.teamide.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;

/**
 * 文件工具类
 *
 */
public class FileUtil {

	/**
	 * 判断是否是图片
	 * 
	 * @param file
	 *            需要判定的文件
	 * @return 返回是否是图片
	 * @throws IOException
	 *             IO异常
	 */
	public static boolean isImage(File file) throws IOException {

		ImageInputStream iis = null;
		try {
			iis = ImageIO.createImageInputStream(file);

			Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
			if (!iter.hasNext()) {
				return false;
			}

			return true;
		} finally {
			IOUtil.close(iis);
		}
	}

	/**
	 * 读取路径下所有文件
	 * 
	 * @param path
	 *            读取路径
	 * @return 返回文件路径和二进制键值对
	 * @throws IOException
	 *             IO异常
	 */
	public static Map<URL, byte[]> readAllFiles(String path) throws IOException {

		Map<URL, byte[]> map = new HashMap<URL, byte[]>();
		if (StringUtil.isEmpty(path)) {
			return map;
		}
		appendAllFiles(path, map);
		return map;
	}

	public static void appendAllFiles(String path, Map<URL, byte[]> map) throws IOException {

		if (StringUtil.isEmpty(path)) {
			return;
		}
		File file = new File(path);
		if (file != null) {
			if (file.isDirectory()) {
				File[] fs = file.listFiles();
				for (File f : fs) {
					appendAllFiles(f.getAbsolutePath(), map);
				}
			} else if (file.isFile()) {
				String absolutePath = file.getAbsolutePath();

				byte[] bytes = read(absolutePath);

				map.put(file.toURI().toURL(), bytes);
			}
		}

	}

	/**
	 * 读取文件
	 * 
	 * @param path
	 *            读取的文件路径
	 * @return 文件的二进制
	 * @throws IOException
	 *             IO异常
	 */
	public static byte[] read(String path) throws IOException {

		if (StringUtil.isEmpty(path)) {
			return null;
		}
		File file = new File(path);
		return read(file);
	}

	/**
	 * 读取文件
	 * 
	 * @param file
	 *            读取的文件
	 * @return 文件二进制
	 * @throws IOException
	 *             IO异常
	 */
	public static byte[] read(File file) throws IOException {

		if (null == file || !file.isFile()) {
			return null;
		}
		FileInputStream stream = new FileInputStream(file);
		return IOUtil.read(stream);
	}

	/**
	 * 写入文件
	 * 
	 * @param bytes
	 *            二进制数据
	 * @param file
	 *            写入的文件
	 * @return 是否成功
	 * @throws IOException
	 *             IO异常
	 */
	public static boolean write(byte[] bytes, File file) throws IOException {

		boolean flag = false;
		FileOutputStream o = null;
		try {
			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}
			if (!file.exists()) {
				file.createNewFile();
			}
			o = new FileOutputStream(file);
			o.write(bytes);
			flag = true;
		} finally {
			IOUtil.close(o);
		}
		return flag;
	}

	/**
	 * 加载所有文件
	 * 
	 * @param path
	 *            加载的路径
	 * @return 所有文件列表
	 */
	public static List<File> loadAllFiles(String path) {

		List<File> files = new ArrayList<File>();
		appendAllFiles(path, files);
		return files;
	}

	public static void appendAllFiles(String path, List<File> files) {

		if (StringUtil.isEmpty(path)) {
			return;
		}
		File file = new File(path);
		if (!file.exists()) {
			return;
		}
		if (file.isFile()) {
			files.add(file);
		} else if (file.isDirectory()) {
			File[] fs = file.listFiles();
			for (File f : fs) {
				appendAllFiles(f.getAbsolutePath(), files);
			}
		}

	}

	/**
	 * 根据文件名称排序
	 * 
	 * @param files
	 *            文件集合
	 */
	public static void orderByName(List<File> files) {
		Collections.sort(files, new Comparator<File>() {
			@Override
			public int compare(File o1, File o2) {
				if (o1.isDirectory() && o2.isFile())
					return -1;
				if (o1.isFile() && o2.isDirectory())
					return 1;
				return o1.getName().compareTo(o2.getName());
			}
		});
	}

	/**
	 * 根据文件日期排序
	 * 
	 * @param files
	 *            文件集合
	 */
	public static void orderByDate(List<File> files) {
		Collections.sort(files, new Comparator<File>() {
			public int compare(File f1, File f2) {
				long diff = f1.lastModified() - f2.lastModified();
				if (diff > 0)
					return 1;
				else if (diff == 0)
					return 0;
				else
					return -1;// 如果 if 中修改为 返回-1 同时此处修改为返回 1 排序就会是递减
			}

			public boolean equals(Object obj) {
				return true;
			}
		});
	}

	/**
	 * 根据文件长度排序
	 * 
	 * @param files
	 *            文件集合
	 */
	public static void orderByLength(List<File> files) {
		Collections.sort(files, new Comparator<File>() {
			public int compare(File f1, File f2) {
				long diff = f1.length() - f2.length();
				if (diff > 0)
					return 1;
				else if (diff == 0)
					return 0;
				else
					return -1;// 如果 if 中修改为 返回-1 同时此处修改为返回 1 排序就会是递减
			}

			public boolean equals(Object obj) {
				return true;
			}
		});
	}

	/**
	 * 追加内容到文件
	 * 
	 * @param line
	 *            追加内容
	 * @param file
	 *            追加文件
	 * @throws IOException
	 *             IO异常
	 */
	public static void append(String line, File file) throws IOException {
		append(line, file, Charset.forName("UTF-8"));
	}

	/**
	 * 
	 * 追加内容到文件
	 * 
	 * @param line
	 *            追加内容
	 * @param file
	 *            追加文件
	 * @param charset
	 *            编码
	 * @throws IOException
	 *             IO异常
	 */
	public static void append(String line, File file, Charset charset) throws IOException {
		OutputStreamWriter osw = null;
		try {
			FileOutputStream fos = null;
			if (!file.exists()) {
				if (!file.getParentFile().exists()) {
					file.getParentFile().mkdirs();
				}
				file.createNewFile();// 如果文件不存在，就创建该文件
				fos = new FileOutputStream(file);// 首次写入获取
			} else {
				// 如果文件已存在，那么就在文件末尾追加写入
				fos = new FileOutputStream(file, true);// 这里构造方法多了一个参数true,表示在文件末尾追加写入
			}

			osw = new OutputStreamWriter(fos, charset);// 指定以UTF-8格式写入文件

			osw.write(line);

		} finally {
			// 写入完成关闭流
			osw.close();
		}
	}

	/**
	 * 根据文件扩展名获得MimeType
	 * 
	 * @param filePath
	 *            文件路径或文件名
	 * @return MimeType
	 */
	public static String getMimeType(String filePath) {

		return URLConnection.getFileNameMap().getContentTypeFor(filePath);
	}

}
